package mutilthread;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.locks.Lock;

/**
 * Created with IntelliJ IDEA.
 * Description: 模拟实现一个阻塞队列
 * User: Li_yizYa
 * Date: 2025—03—31
 * Time: 20:53
 */
// 此处不考虑泛型参数，只是基于 String 进行存储
class MyBlockingQueue {
    private String[] data = null;
    private volatile int tail = 0;
    private volatile int head = 0;
    private volatile int size = 0;

    private Object Locker = new Object();

    public MyBlockingQueue(int capacity) {
        data = new String[capacity];
    }

    public void put(String s) throws InterruptedException {
        // 加锁的对象可以是 this，也可以是定义的 Locker
        synchronized (Locker) {
            while (size == data.length) {//此处用while 是因为wait并非只能 notify 唤醒，也可能会因为 interrupt 被唤醒
                // 队列满了
                //return;
                Locker.wait();
            }
            data[tail] = s;
            tail++;
            if (tail >= data.length) {
                tail = 0;
            }
            size++;

            Locker.notify();
        }
    }

    public String take() throws InterruptedException {
        String ret = "";
        synchronized (Locker) {
            while (size == 0) {
                // 队列为空
                //return null;
                // 当 queue 为空时，进入阻塞状态
                Locker.wait();
            }

            ret = data[head];
            head++;
            if (head >= data.length) {
                head = 0;
            }
            size--;

            Locker.notify();
        }
        return ret;
    }
}
public class Demo17 {
    public static void main(String[] args) {
        MyBlockingQueue queue = new MyBlockingQueue(1000);

        //生产者线程
        Thread t1 = new Thread(() -> {
            int i = 1;
            while (true) {
                try {
                    queue.put("" + i);
                    System.out.println("生产元素 " + i);
                    i++;

                    //给生产操作，加上 sleep， 生产慢点，消费快点
//                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });

        //消费者线程
        Thread t2 = new Thread(() -> {
            while (true) {
                try {
                    Integer i = Integer.parseInt(queue.take());
                    System.out.println("消费元素 " + i);
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });

        t1.start();
        t2.start();
    }
}
